<script lang="ts" setup>
import type { FileUploadItem } from './types';

import { computed } from 'vue';

import { CheckOne, CloseOne, PauseOne, Refresh } from '@icon-park/vue-next';

import Button from '#/components/fluentui/Button.vue';
import ProgressBar from '#/components/fluentui/ProgressBar.vue';
import { getFileIconComponent } from '#/utils/icon';

interface Props {
  item: FileUploadItem;
  showRemove?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  showRemove: true,
});

const emit = defineEmits<{
  cancel: [id: string];
  remove: [id: string];
  retry: [id: string];
}>();

// 计算进度百分比
const progressPercentage = computed(() => {
  if (!props.item.progress) return 0;
  return Math.round(props.item.progress.progressPercentage);
});

// 格式化上传速度
const formatSpeed = (bytesPerSecond: number): string => {
  if (
    !bytesPerSecond ||
    bytesPerSecond <= 0 ||
    !Number.isFinite(bytesPerSecond)
  )
    return '0 B/s';
  const k = 1024;
  const sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s'];
  const i = Math.floor(Math.log(bytesPerSecond) / Math.log(k));
  const value = bytesPerSecond / k ** i;
  return `${value.toFixed(i === 0 ? 0 : 1)} ${sizes[i]}`;
};

// 格式化剩余时间
const formatRemainingTime = (seconds: number): string => {
  if (!seconds || seconds <= 0 || !Number.isFinite(seconds)) return '--';

  if (seconds < 60) {
    return `${Math.ceil(seconds)}秒`;
  } else if (seconds < 3600) {
    const minutes = Math.ceil(seconds / 60);
    return `${minutes}分钟`;
  } else {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.ceil((seconds % 3600) / 60);
    if (minutes === 60) {
      return `${hours + 1}小时`;
    }
    return hours > 0
      ? `${hours}小时${minutes > 0 ? `${minutes}分钟` : ''}`
      : `${minutes}分钟`;
  }
};

// 计算上传速度和剩余时间显示
const speedText = computed(() => {
  if (!props.item.progress || props.item.status !== 'uploading') return '';

  const { totalBytesWritten, totalContentLength } = props.item.progress;
  // const remainingBytes = totalContentLength - totalBytesWritten;

  // 这里可以根据实际情况计算速度，现在返回简单的进度信息
  return `${formatFileSize(totalBytesWritten)} / ${formatFileSize(totalContentLength)}`;
});

// 计算MD5进度百分比
const md5ProgressPercentage = computed(() => {
  if (!props.item.md5Progress) return 0;
  return Math.round(props.item.md5Progress.percentage);
});

// 格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes === 0) return '0 Bytes';

  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
};

// 获取状态显示文本
const statusText = computed(() => {
  switch (props.item.status) {
    case 'calculating-md5': {
      return 'MD5计算中...';
    }
    case 'cancelled': {
      return '已取消';
    }
    case 'error': {
      return '上传失败';
    }
    case 'pending': {
      return '等待上传';
    }
    case 'success': {
      return '上传成功';
    }
    case 'uploading': {
      return '上传中...';
    }
    default: {
      return '';
    }
  }
});

// 获取状态颜色
const statusColor = computed(() => {
  switch (props.item.status) {
    case 'calculating-md5': {
      return 'text-blue-600';
    }
    case 'cancelled': {
      return 'text-gray-500';
    }
    case 'error': {
      return 'text-red-600';
    }
    case 'pending': {
      return 'text-blue-600';
    }
    case 'success': {
      return 'text-green-600';
    }
    case 'uploading': {
      return 'text-blue-600';
    }
    default: {
      return 'text-gray-600';
    }
  }
});

// 获取进度条状态
const progressValidationState = computed(() => {
  switch (props.item.status) {
    case 'error': {
      return 'error';
    }
    case 'success': {
      return 'success';
    }
    default: {
      return undefined;
    }
  }
});
</script>

<template>
  <div
    class="bg-accent flex items-center justify-between rounded-lg p-4 transition-colors"
  >
    <div class="flex flex-1 items-center space-x-3">
      <!-- 文件图标 -->
      <div class="text-2xl text-gray-600">
        <component :is="getFileIconComponent(item.name)" size="24" />
      </div>

      <!-- 文件信息 -->
      <div class="min-w-0 flex-1">
        <p class="truncate text-sm font-medium">
          {{ item.name }}
        </p>
        <p class="text-muted-foreground text-xs">
          {{ formatFileSize(item.size) }}
        </p>

        <!-- MD5计算进度 -->
        <div
          v-if="item.status === 'calculating-md5' && item.md5Progress"
          class="mt-2"
        >
          <ProgressBar
            :value="md5ProgressPercentage"
            :max="100"
            thickness="medium"
            shape="rounded"
            validation-state="success"
            class="w-full"
          />
          <div class="text-muted-foreground mt-1 flex justify-between text-xs">
            <span :class="statusColor">{{ statusText }}</span>
            <span class="text-blue-600">{{ md5ProgressPercentage }}%</span>
          </div>
        </div>

        <!-- 进度条 -->
        <div
          v-else-if="item.status === 'uploading' || item.status === 'success'"
          class="mt-2"
        >
          <ProgressBar
            :value="progressPercentage"
            :max="100"
            thickness="medium"
            shape="rounded"
            :validation-state="progressValidationState"
            class="w-full"
          />
          <div class="text-muted-foreground mt-1 flex justify-between text-xs">
            <span :class="statusColor">{{ statusText }}</span>
            <div
              v-if="item.status === 'uploading' && item.progress"
              class="flex items-center space-x-2"
            >
              <span
                v-if="
                  item.progress.uploadSpeed &&
                  item.progress.uploadSpeed > 0 &&
                  Number.isFinite(item.progress.uploadSpeed)
                "
                class="text-primary"
              >
                {{ formatSpeed(item.progress.uploadSpeed) }}
              </span>
              <span
                v-if="
                  item.progress.remainingTime &&
                  item.progress.remainingTime > 0 &&
                  Number.isFinite(item.progress.remainingTime)
                "
                class="text-primary/70"
              >
                {{ formatRemainingTime(item.progress.remainingTime) }}
              </span>
              <span v-else-if="speedText">{{ speedText }}</span>
            </div>
          </div>
        </div>

        <!-- 错误信息 -->
        <div v-else-if="item.status === 'error'" class="mt-2">
          <p :class="statusColor" class="text-xs">{{ statusText }}</p>
          <p v-if="item.error" class="mt-1 text-xs text-red-500">
            {{ item.error }}
          </p>
        </div>

        <!-- 其他状态 -->
        <div v-else class="mt-1">
          <span :class="statusColor" class="text-xs">{{ statusText }}</span>
        </div>
      </div>
    </div>

    <!-- 操作按钮 -->
    <div class="flex items-center space-x-2">
      <!-- 重试按钮 -->
      <Button
        v-if="item.status === 'error'"
        appearance="subtle"
        size="small"
        @click="emit('retry', item.id)"
        title="重试上传"
      >
        <Refresh size="16" />
      </Button>

      <!-- 取消按钮 -->
      <Button
        v-if="item.status === 'uploading'"
        appearance="subtle"
        size="small"
        @click="emit('cancel', item.id)"
        title="取消上传"
      >
        <PauseOne size="16" />
      </Button>

      <!-- 成功标识 -->
      <div v-if="item.status === 'success'" class="text-green-600">
        <CheckOne size="20" />
      </div>

      <!-- 移除按钮 -->
      <Button
        v-if="
          showRemove &&
          (item.status === 'pending' ||
            item.status === 'error' ||
            item.status === 'cancelled' ||
            item.status === 'success')
        "
        appearance="subtle"
        @click="emit('remove', item.id)"
        title="移除文件"
        icon-only
      >
        <CloseOne size="16" />
      </Button>
    </div>
  </div>
</template>
